package main

import (
	"chat/data"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

// User 定义一个用户结构体
type User struct {
	//注意这里的是反引号 不是单引号 这表示他是 JSON 标签
	HeadPortrait string `json:"head portrait"`
	Username     string `json:"username"`
	Password     string `json:"password"`
	Bool         bool   `json:"bool"` //true表示需要头像 false表示不需要
}

// 注册
func createUser(w http.ResponseWriter, r *http.Request) {
	var newUser User
	//json.NewDecoder().Decode(&newUser) 主要用于从输入流中解析JSON 并存放到指定位置
	//将json数据 储存到newUser中
	err := json.NewDecoder(r.Body).Decode(&newUser)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	// 获取请求头中的Remote Address，它通常包含客户端IP和端口号
	remoteAddr := r.RemoteAddr
	// 但在代理环境下，客户端IP可能被封装在X-Forwarded-For头部
	// 需要检查并解析该头部以获取客户端的真实IP地址
	forwardedFor := r.Header.Get("X-Forwarded-For")
	if forwardedFor != "" {
		// X-Forwarded-For可能包含多个IP地址，最左边的是离客户端最近的IP
		remoteAddr = strings.Split(forwardedFor, ", ")[0]
	}
	Ip := strings.Split(remoteAddr, ":")[0]

	//将数据写入数据库
	i := data.Insert(newUser.Username, newUser.Password, Ip)
	switch i {
	case 0:
		w.WriteHeader(http.StatusInternalServerError) // 其他错误，返回500状态码
	case 1:
		w.WriteHeader(http.StatusConflict) // 用户已存在，返回409状态码
	case 2:
		w.WriteHeader(http.StatusOK) // 用户创建成功，返回200状态码

		// 解码 Base64 图像数据并保存到文件
		decodedData, err := base64.StdEncoding.DecodeString(newUser.HeadPortrait)
		if err != nil {
			fmt.Println("Error decoding base64 data:", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// 将解码后的数据写入文件
		err = ioutil.WriteFile("./userData/"+newUser.Username+"_HeadPortrait.jpg", decodedData, 0644)
		if err != nil {
			fmt.Println("Error writing file:", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
	}
	w.Header().Set("Content-Type", "application/json")
}

func register(w http.ResponseWriter, r *http.Request) {
	var newUser User
	err := json.NewDecoder(r.Body).Decode(&newUser)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	i := data.Verification(newUser.Username, newUser.Password)
	switch i {
	case 0:
		w.WriteHeader(http.StatusOK) // 登陆成功200

		if newUser.Bool {
			w.Header().Set("Content-Type", "image/jpeg")
			imgFile, err := os.Open("./userData/" + newUser.Username + "_HeadPortrait.jpg") //读取图片
			if err != nil {
				http.Error(w, "Failed to open image file", http.StatusInternalServerError)
				return
			}
			defer imgFile.Close()

			_, err = io.Copy(w, imgFile)
			if err != nil {
				http.Error(w, "Failed to copy image data", http.StatusInternalServerError)
				return
			}
		}

		// 获取请求头中的Remote Address，它通常包含客户端IP和端口号
		remoteAddr := r.RemoteAddr
		// 但在代理环境下，客户端IP可能被封装在X-Forwarded-For头部
		// 需要检查并解析该头部以获取客户端的真实IP地址
		forwardedFor := r.Header.Get("X-Forwarded-For")
		if forwardedFor != "" {
			// X-Forwarded-For可能包含多个IP地址，最左边的是离客户端最近的IP
			remoteAddr = strings.Split(forwardedFor, ", ")[0]
		}
		Ip := strings.Split(remoteAddr, ":")[0]

		data.AmendIP(newUser.Username, Ip)
	case 1:
		w.WriteHeader(http.StatusNotFound) //用户不存在404
	case 2:
		w.WriteHeader(http.StatusUnauthorized) //密码错误401
	}
}

// w http.ResponseWriter：这是一个接口，提供对HTTP响应的控制。你可以通过它设置响应头和写入响应主体。
// r *http.Request：这是一个指向HTTP请求的指针，包含了客户端请求的所有信息（如请求方法、URL、头信息等）。
func home(w http.ResponseWriter, r *http.Request) {
	//设置HTTP响应的头信息，指定响应内容的类型为text/html。
	w.Header().Set("Content-Type", "text/html")

	// 获取请求头中的Remote Address，它通常包含客户端IP和端口号
	remoteAddr := r.RemoteAddr

	// 但在代理环境下，客户端IP可能被封装在X-Forwarded-For头部
	// 需要检查并解析该头部以获取客户端的真实IP地址
	forwardedFor := r.Header.Get("X-Forwarded-For")
	if forwardedFor != "" {
		// X-Forwarded-For可能包含多个IP地址，最左边的是离客户端最近的IP
		remoteAddr = strings.Split(forwardedFor, ", ")[0]
	}

	//向HTTP响应的主体部分写入内容
	fmt.Fprintf(w, "<h1>Welcome to the Go HTTP Server</h1>")
	fmt.Fprintf(w, "Client IP address: %s", strings.Split(remoteAddr, ":")[0])

	fmt.Println("成功连接")
}

func inquire(w http.ResponseWriter, r *http.Request) {
	// 读取请求体
	requestBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if data.Query(string(requestBody)) == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	w.Header().Set("Content-Type", "image/jpeg")
	fmt.Println(string(requestBody))
	imgFile, err := os.Open("./userData/" + string(requestBody) + "_HeadPortrait.jpg") //读取图片
	if err != nil {
		http.Error(w, "Failed to open image file", http.StatusInternalServerError)
		return
	}
	defer imgFile.Close()

	_, err = io.Copy(w, imgFile)
	if err != nil {
		http.Error(w, "Failed to copy image data", http.StatusInternalServerError)
		return
	}
	// w.WriteHeader(http.StatusOK)
}

func main() {
	err := data.Connect()
	if err != nil {
		fmt.Println("连接失败~")
	}
	go data.TcpConnect()
	//将url路径与函数关联 当访问路径时 触发相应的函数
	http.HandleFunc("/", home)
	http.HandleFunc("/inquire", inquire)
	http.HandleFunc("/register", register)
	http.HandleFunc("/register/create", createUser)

	fmt.Println("Starting server at port 8080...")
	//阻塞调用表示如果该操作不能立即完成，程序会暂停执行，等待该操作完成后再继续
	//阻塞调用启动一个HTTP服务器 并且允许所有网络访问8080端口  nil表示使用默认的多路复用器
	if err := http.ListenAndServe("0.0.0.0:8080", nil); err != nil { //程序停止 直到有了http请求 再执行相应函数
		//当err不为nil时 表示服务器启动失败 这行代码会记录一条格式化的致命错误消息
		log.Fatalf("Could not start server: %s\n", err.Error())
	}

}
